跳到主要内容

使用 Docker compose 编排容器

什么是 Docker Compose?有什么用?

Docker Compose 是 Docker 官方的容器编排(Orchestration)项目之一,使用 Python 编写。通过 Docker Compose,开发者可以使用 YAML 文件来配置应用的所有服务,然后只需一个简单的命令即可创建和启动所有服务。

Docker Compose 是一个开源项目,你可以在 这里 找到它的源代码。

Docker Compose 的核心功能:

  • 多容器管理:允许用户在一个 YAML 文件中定义和管理多个容器。
  • 服务编排:配置容器间的网络和依赖关系。
  • 一键部署:通过简单的命令,如docker-compose updocker-compose down,可以轻松地启动和停止整个应用程序。

Docker Compose 简化了多容器应用程序的开发、测试和部署过程,同时降低了应用程序的部署复杂度和管理成本。

安装 Docker Compose

Docker Compose 通常与 Docker 一起安装,尤其是在 Docker Desktop 中已经包含了 Docker Compose。如果你使用的是 Linux 系统,可能需要单独安装 Docker Compose。

apt install -y docker-compose

这种安装方式安装的是旧版 的 Docker Compose(V1),它的本质是一个 Python 脚本。 最新版的 Docker Compose V2 使用 Go 语言编写,并作为 Docker CLI 的一个插件进行分发。仓库地址 https://github.com/docker/compose 你可以从这个存储库的发布页面下载 Docker Compose 二进制文件。 将适用于你操作系统的相关二进制文件重命名为 docker-compose,并将其复制到 $HOME/.docker/cli-plugins 或者将其复制到以下其中一个文件夹以进行全局安装: /usr/local/lib/docker/cli-plugins 或 /usr/local/libexec/docker/cli-plugins /usr/lib/docker/cli-plugins 或 /usr/libexec/docker/cli-plugins (可能需要使用 chmod +x 使下载的文件可执行)

docker-compose.yml 文件基本结构

Docker Compose 文件是 Docker Compose 工具的核心,用于定义和配置多容器 Docker 应用。

这个文件通常命名为 docker-compose.yml,采用 YAML(YAML Ain't Markup Language)格式编写。

关于 YAML 的具体语法可以参考 这里

Docker Compose 文件基本结构如下:

  • 版本(version): 指定 Compose 文件格式的版本。版本决定了可用的配置选项。

  • 服务(services)

    定义了应用中的每个容器(服务)。每个服务可以使用不同的镜像、环境设置和依赖关系。

    • 镜像(image): 从指定的镜像中启动容器,可以是存储仓库、标签以及镜像 ID。
    • 命令(command): 可选,覆盖容器启动后默认执行的命令。在启动服务时运行特定的命令或脚本,常用于启动应用程序、执行初始化脚本等。
    • 端口(ports): 可选,映射容器和宿主机的端口。
    • 依赖(depends_on): 依赖配置的选项,意思是如果服务启动是如果有依赖于其他服务的,先启动被依赖的服务,启动完成后在启动该服务。
    • 环境变量(environment): 可选,设置服务运行所需的环境变量。
    • 重启(restart): 可选,控制容器的重启策略。在容器退出时,根据指定的策略自动重启容器。
    • 服务卷(volumes): 可选,定义服务使用的卷,用于数据持久化或在容器之间共享数据。
    • 构建(build): 指定构建镜像的 dockerfile 的上下文路径,或者详细配置对象。
  • 网络(networks): 定义了容器间的网络连接。

  • 卷(volumes): 用于数据持久化和共享的数据卷定义。常用于数据库存储、配置文件、日志等数据的持久化。

version: "3.8" # 定义版本, 表示当前使用的 docker-compose 语法的版本
services: # 服务,可以存在多个
servicename1: # 服务名字,它也是内部 bridge 网络可以使用的 DNS name,如果不是集群模式相当于 docker run 的时候指定的一个名称,
#集群(Swarm)模式是多个容器的逻辑抽象
image: # 镜像的名字
command: # 可选,如果设置,则会覆盖默认镜像里的 CMD 命令
environment: # 可选,等价于 docker container run 里的 --env 选项设置环境变量
volumes: # 可选,等价于 docker container run 里的 -v 选项 绑定数据卷
networks: # 可选,等价于 docker container run 里的 --network 选项指定网络
ports: # 可选,等价于 docker container run 里的 -p 选项指定端口映射
restart: # 可选,控制容器的重启策略
build: #构建目录
depends_on: #服务依赖配置
servicename2:
image:
command:
networks:
ports:
servicename3:
#...
volumes: # 可选,需要创建的数据卷,类似 docker volume create
db_data:
networks: # 可选,等价于 docker network create

Docker Compose 常用命令

  • 启动 使用 docker-compose up 命令,会根据 docker-compose.yml 文件中定义的服务来创建和启动容器,并将它们连接到默认的网络中。
# 在当前目录下寻找 docker-compose.yml 文件,并根据其中定义的服务启动应用程序
docker-compose up

# 后台启动
docker-compose up -d

# 强制重新创建所有容器,即使它们已经存在
docker-compose up --force-recreate

# 重新构建镜像
docker-compose up --build

# 指定要启动的服务名称,而不是启动所有服务
# 可以同时指定多个服务,用空格分隔。
docker-compose up service_name

另外,如果 Compose 文件名称不是 docker-compose.yml 也没问题,可以通过 -f 参数指定。

docker-compose -f docker-compose.prod.yml up

这个参数对其他 docker compose 命令也适用。

  • 暂停 docker-compose down 命令用于停止并移除通过 docker-compose up 启动的容器和网络。
# 在当前目录下寻找 docker-compose.yml 文件
# 根据其中定义移除启动的所有容器,网络和卷。
docker-compose down
# 停止容器但不移除
docker-compose down --stop
# 指定要停止和移除的特定服务,而不是停止和移除所有服务
# 可以同时指定多个服务,用空格分隔。
docker-compose down service_name
  • 查看 docker-compose ps 命令用于查看通过 docker-compose up 启动的所有容器的状态信息。
# 查看所有容器的状态信息
docker-compose ps

# 只显示服务名称
docker-compose ps --services

# 查看指定服务的容器
docker-compose ps service_name
  • 其他命令

    命令介绍
    docker-compose version查看 docker compose 的版本
    docker-compose images列出所有容器使用的镜像
    docker-compose kill强制停止服务的容器
    docker-compose exec在容器中执行命令
    docker-compose logs查看日志
    docker-compose pause暂停服务
    docker-compose unpause恢复服务
    docker-compose push推送服务镜像
    docker-compose start启动当前停止的某个容器
    docker-compose stop停止当前运行的某个容器
    docker-compose rm删除服务停止的容器
    docker-compose top查看进程

示例

https://github.com/lulaide/docker-example/blob/main/example_fullstack/docker-compose.yml

# docker-compose.yml
version: '3.8'

services:
backend:
build: ./backend
ports:
- "8080:8080"
networks:
- app-network
volumes:
- app-data:/data

frontend:
build: ./frontend
ports:
- "5173:80"
networks:
- app-network
# 指定服务依赖,确保 frontend 在 backend 启动后再启动
depends_on:
- backend

# 定义一个自定义网络,让前后端服务可以相互通信
networks:
app-network:
driver: bridge

# 定义一个数据卷,用于后端服务的数据持久化(其实这个示例没用上)
volumes:
app-data:

本地一步启动,它会自动构建并启动前后端服务:

docker-compose up -d

部署时使用的生产环境配置文件:

# docker-compose-prod.yml
version: '3.8'

services:
backend:
# 不再使用 build,而是直接使用预构建好的镜像
image: ghcr.io/lulaide/web-backend:latest
ports:
- "8080:8080"
networks:
- app-network
volumes:
- app-data:/data

frontend:
image: ghcr.io/lulaide/web-frontend:latest
ports:
- "5173:80"
networks:
- app-network
depends_on:
- backend

networks:
app-network:
driver: bridge

volumes:
app-data:

部署时使用:

docker-compose -f docker-compose-prod.yml up -d